home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Tumbler and Podium / Tumbler_file.c < prev    next >
Encoding:
Text File  |  1995-11-13  |  13.9 KB  |  640 lines  |  [TEXT/MPS ]

  1. //        file.c
  2. //
  3. //        File Input/Output routines.
  4. //        
  5. //
  6. //        Author:        Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team
  7. //        Date:        Thursday, January 26, 1992
  8. //
  9. //    Modification History:
  10. //
  11. //        11/27/94    nick        there seems to be a problem reading metafiles into the app
  12. //        01/25/95    nick        slotted in spin code (thanks kent), updated for viewhints.  
  13. //                                If we have view hints, then we can export things like the 
  14. //                                renderer type and lighting and camera in a drag or cut/copy
  15. //
  16. //
  17. //    To Do:
  18. //         factor for AppleEvents
  19. //
  20. //        Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  21.  
  22. #include "Tumbler_globals.h"
  23. #include "Tumbler_prototypes.h"
  24. #include "Tumbler_resources.h"
  25.  
  26. #include "QD3DStorage.h"
  27. #include "QD3DGroup.h"
  28. #include "QD3DIO.h"
  29. #include "QD3DShader.h"
  30. #include "QD3DView.h"
  31.  
  32. #include "Tumbler_file.h"
  33. #include "Tumbler_camera.h"
  34. #include "Tumbler_document.h"
  35. #include "Tumbler_PICTImport.h"
  36. #include "Tumbler_utility.h"
  37.  
  38.  
  39. #include <string.h>
  40.  
  41. static OSErr WriteDocumentFile(DocumentPtr theDocument);
  42. //-----------------------------------------------------------------------------
  43.  
  44. TQ3Status Tumbler_ReadScene(
  45.     TQ3FileObject        file,
  46.     short                isText,
  47.     TQ3SharedObject        *viewHints,
  48.     TQ3Object            *model)
  49. {
  50.     char                filename[64];
  51. //    TQ3Object            group;
  52.     TQ3Object            object;
  53.     TQ3Boolean            isEOF;
  54.     
  55.     *viewHints    = NULL;
  56.     if( *model ) {
  57.         Q3Object_Dispose(*model);
  58.     }
  59.  
  60.     *model        = Q3DisplayGroup_New();
  61.  
  62. //    group        = NULL;
  63.     object        = NULL;
  64.     
  65.     SetCursor(*GetCursor(watchCursor));
  66.  
  67.     if (Q3File_OpenRead(file, NULL) != kQ3Success)
  68.     {
  69.         SetCursor(&qd.arrow);
  70.         return kQ3Failure;
  71.     }
  72.  
  73.     while ((isEOF = Q3File_IsEndOfFile(file)) == kQ3False)
  74.     {
  75.         object = NULL;
  76.         
  77.         object = Q3File_ReadObject(file);
  78.         
  79.         if (object == NULL) 
  80.         {
  81.             /* 
  82.                 Check and handle errors here - 
  83.                     Some errors may mean more objects are left in the file.
  84.             */
  85.             break;
  86.         }
  87.  
  88.         if (Q3Object_IsType(object, kQ3SharedTypeViewHints))
  89.         {
  90.             if (*viewHints == NULL)
  91.             {
  92.                 *viewHints = object;
  93.                 object = NULL;
  94.             }
  95.         }
  96.         else if (Q3Object_IsDrawable(object))
  97.         {
  98.             if (*model)
  99.             {
  100.                 Q3Group_AddObject(*model, object);
  101.             }
  102. //            else
  103. //            {
  104. //                group = Q3DisplayGroup_New();
  105. //
  106. //                Q3Group_AddObject(group, *model);
  107. //                Q3Group_AddObject(group, object);
  108. //                Q3Object_Dispose(*model);
  109. //
  110. //                *model = group;
  111. //            }
  112.         }
  113.         if (object != NULL) 
  114.             Q3Object_Dispose(object);
  115.     }
  116.             
  117.     Q3File_Close(file);
  118.     
  119.     if (isEOF == kQ3False)
  120.     {
  121.         if (*model != NULL)
  122.         {    Q3Object_Dispose(*model); *model = NULL; }
  123.     
  124.         if (*viewHints != NULL)
  125.         {    Q3Object_Dispose(*viewHints); *viewHints = NULL; }
  126.         
  127.         SetCursor(&qd.arrow);
  128.         return kQ3Failure;
  129.     }
  130.     
  131.     SetCursor(&qd.arrow);
  132.     return kQ3Success;
  133. }
  134.  
  135. //-----------------------------------------------------------------------------
  136. //
  137. //    Tumbler_WriteScene()
  138. //
  139.  
  140. void Tumbler_WriteScene(
  141.     TQ3FileObject        file,
  142.     short                textMode,
  143.     DocumentPtr            theDocument)
  144. {
  145.     TQ3GroupPosition    gPos;
  146.     TQ3Object            object;
  147.     TQ3ViewStatus        fileStatus;
  148.     
  149.     SetCursor(*GetCursor(watchCursor));
  150.  
  151.     if (Q3File_OpenWrite(file, kQ3FileModeText) != kQ3Success)
  152.     {
  153.         SetCursor(&qd.arrow);
  154.         return;
  155.     }
  156.     
  157.     Q3View_StartWriting(theDocument->theView, file);
  158.         
  159.     if (theDocument->viewHints != NULL)
  160.     {
  161.         if (Q3Object_Submit(theDocument->viewHints, theDocument->theView) == kQ3Failure)
  162.         {
  163.             Q3File_Cancel(file);
  164.             SetCursor(&qd.arrow);
  165.             return;
  166.         }
  167.     }
  168.     do {
  169.         if (theDocument->documentGroup != NULL)
  170.         {
  171.                 Q3Group_GetFirstPosition(theDocument->documentGroup, &gPos);
  172.                 while (gPos)
  173.                 {
  174.                     TQ3Status status;
  175.                     
  176.                     Q3Group_GetPositionObject(theDocument->documentGroup, gPos, &object);
  177.                     status = Q3Object_Submit(object, theDocument->theView);
  178.                     Q3Object_Dispose(object);
  179.                     
  180.                     if (status != kQ3Failure)
  181.                     {
  182.                         Q3Group_GetNextPosition(theDocument->documentGroup, &gPos);
  183.                     }
  184.                 }
  185.         }
  186.     } while ((fileStatus = Q3View_EndWriting(theDocument->theView)) == kQ3ViewStatusRetraverse);
  187.         
  188.     if( Q3File_Close(file) == kQ3Failure ) {
  189.         SetCursor(&qd.arrow);
  190.         return;
  191.     }
  192.     SetCursor(&qd.arrow);
  193.     return ;
  194. }
  195.  
  196.  
  197. //-----------------------------------------------------------------------------
  198. // ReadDocumentFile
  199.  
  200. short ReadDocumentFile(DocumentPtr theDocument, TQ3Boolean isText)
  201. {
  202.     TQ3StorageObject        storage;
  203.     TQ3FileObject        fd;
  204.     TQ3Object             objects = nil;
  205.     TQ3Object            viewHints;    
  206.     
  207.     storage = Q3MacintoshStorage_New( theDocument->fRefNum );
  208.     
  209.     if (storage == nil)
  210.         goto bail;
  211.     
  212.     fd = Q3File_New();
  213.     
  214.     if (fd == nil)
  215.         goto bail;
  216.  
  217.     Q3File_SetStorage(fd, storage);
  218.     Q3Object_Dispose(storage);
  219.     
  220.     Tumbler_ReadScene(
  221.         fd,
  222.         isText,
  223.         &viewHints,
  224.         &theDocument->documentGroup) ;
  225.     
  226.     TumblerDocument_UpdateView( theDocument, viewHints ) ;
  227.     
  228.     AdjustLightsPositions(theDocument);
  229.  
  230.     if (viewHints)
  231.         Q3Object_Dispose(viewHints);
  232.  
  233.     Q3Object_Dispose(fd);
  234.  
  235.     return(noErr);
  236. bail:
  237.     Q3Object_Dispose(fd);
  238.  
  239.     return(fnOpnErr);
  240. }
  241.  
  242. //-
  243.  
  244. PicHandle OpenPICTFile(
  245.     FSSpec *theFile)
  246. {
  247.     OSErr        err;
  248.     long        curEOF;
  249.     PicHandle    my_pic;
  250.     long         count;
  251.     Ptr         buffer;
  252.     short        refNum;
  253.     
  254.     if (FSpOpenDF(theFile, fsRdWrPerm, &refNum))
  255.         return(0);
  256.  
  257.     /* get size of file */
  258.     err = GetEOF(refNum, &curEOF);
  259.     if (err != 0) {
  260.         return(0);
  261.     }
  262.     
  263.     /* move the file mark to 512 */
  264.     err = SetFPos(refNum, fsFromStart, 512L);
  265.     if (err != 0) {
  266.         return(0);
  267.     }
  268.  
  269.     /* size of data to read */
  270.     count = curEOF - 512;
  271.     
  272.     /* create the PicHandle */
  273.     my_pic = (PicHandle)NewHandle(count);
  274.     HLock((Handle)my_pic);
  275.     
  276.     /* read the PICT info */
  277.     buffer = (Ptr)(*my_pic);
  278.     err = FSRead(refNum, &count, buffer);
  279.     if (err != 0) {
  280.         return(0);
  281.     }
  282.     HUnlock((Handle)my_pic);
  283.  
  284.     FSClose(refNum);
  285.     
  286.     return (my_pic);
  287. }
  288.  
  289.  
  290.  
  291. OSErr WriteDocumentFile(DocumentPtr theDocument)
  292. {
  293.     OSErr        theResult;
  294.     long        length;
  295.     char        *bufPtr;
  296.  
  297.     SetCursor(*GetCursor(watchCursor));
  298.  
  299.     if (! theDocument->fRefNum)
  300.         return(fnOpnErr);
  301.  
  302.     if ((theResult = SetFPos(theDocument->fRefNum, fsFromStart, 0)) != noErr ) 
  303.         return(theResult);
  304.  
  305.     if( theDocument->documentGroup ) {
  306.         TQ3StorageObject    storage;
  307.         TQ3FileObject    fd;
  308.         
  309.         storage = Q3MacintoshStorage_New(theDocument->fRefNum);
  310.         
  311.         if (storage == nil)
  312.             goto bail;
  313.         
  314.         fd = Q3File_New();
  315.         
  316.         if (fd == nil)
  317.             goto bail;
  318.  
  319.         Q3File_SetStorage(fd, storage);
  320.         Q3Object_Dispose(storage);
  321.         
  322.         Tumbler_WriteScene(fd, 
  323.                             kQ3FileModeText,
  324.                             theDocument) ;
  325.  
  326.         Q3Object_Dispose(fd);
  327.     }
  328.     return(noErr);
  329. bail:
  330.     return(fnOpnErr);
  331. }
  332.  
  333.  
  334. void DoNewDocument(void)
  335.  
  336. {    DocumentPtr theDocument;
  337.  
  338.     if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  339.         ShowWindow(theDocument->theWindow);
  340.     }
  341. }
  342.  
  343. OSErr DoOpenFile(FSSpec *theFile)
  344.  
  345. {    OSErr                result;
  346.     short                refNum;
  347.     DocumentPtr         theDocument;
  348.     FInfo                fndrInfo ;
  349.     TQ3Boolean            isText ;
  350.  
  351.     // we assume the FSSpec passed in was valid, get the file information
  352.     // we need to know the file type, this routine may get called by an appleEvent
  353.     // handler, so we can't assume a type, we need to get it from the fsspec.
  354.     
  355.     FSpGetFInfo( theFile, &fndrInfo ) ;
  356.     
  357.     // pull out the file type
  358.     
  359.     isText = (fndrInfo.fdType == 'TEXT') ;
  360.     
  361.     if ((result = FSpOpenDF(theFile, fsRdWrPerm, &refNum)) != noErr)
  362.         return(result);
  363.  
  364.     if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  365.         theDocument->fRefNum = refNum;
  366.         theDocument->theFileSpec = *theFile ;
  367.         SetCursor(*GetCursor(watchCursor));
  368.         ReadDocumentFile( theDocument, isText ) ;
  369.         SetWTitle(theDocument->theWindow, theFile->name);
  370.         ShowWindow(theDocument->theWindow);
  371.         AdjustCamera(theDocument,
  372.             theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  373.             theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);
  374.         SetCursor(&qd.arrow);
  375.  
  376.     } else {
  377.         SysBeep(1);
  378.         FSClose(refNum);
  379.         return(memFullErr);
  380.     }
  381.     return(noErr);
  382. }
  383.  
  384. void DoImport3DMFDocument(DocumentPtr theDocument)
  385. {
  386.     short                refNum;
  387.     StandardFileReply    theReply;
  388.     SFTypeList            theTypeList = { 'TEXT', '3DMF', 0 };
  389.     short                numtypes = 2 ;
  390.  
  391.     if(theDocument == nil)
  392.         return;
  393.  
  394.     StandardGetFile(0L, numtypes, theTypeList, &theReply);
  395.  
  396.     // read for podium files
  397.     if (theReply.sfGood) {
  398.         if(theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') {
  399.  
  400.             // did we try to open a metafile ???
  401.         
  402.             OSErr                result;
  403.             short                refNum;
  404.             DocumentPtr         theDocument;
  405.             FInfo                fndrInfo ;
  406.             TQ3Boolean            isText ;
  407.             
  408.             isText = (theReply.sfType == 'TEXT') ;
  409.             
  410.             if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr)
  411.                 return ;
  412.                 
  413.             theDocument->fRefNum = refNum;
  414.             
  415.             ReadDocumentFile( theDocument, isText ) ;
  416.             
  417. #ifdef PODIUM_APP
  418.             AdjustCamera(theDocument,
  419.                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  420.                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);
  421. #else
  422.         AdjustCamera(theDocument,
  423.             theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  424.             theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);
  425. #endif
  426.  
  427.         } 
  428.     }
  429. }
  430.  
  431.  
  432. //--------------------------------------------------------------------------------
  433. void DoOpenDocument(DocumentPtr theDocument)
  434. {    short                refNum;
  435.  
  436. #ifndef PODIUM_APP
  437.     SFTypeList            theTypeList = { 'TEXT', '3DMF', 'PICT', 0 };
  438.     short                numtypes = 3 ;
  439. #else
  440.     SFTypeList            theTypeList = { 'PICT', 0 };
  441.     short                numtypes = 1 ;
  442. #endif
  443.  
  444.     StandardFileReply    theReply;
  445.     StandardGetFile(0L, numtypes, theTypeList, &theReply);
  446.  
  447. #ifndef PODIUM_APP
  448.  
  449.     // read for Tumbler files
  450.     if (theReply.sfGood) {
  451.         if( theReply.sfType == 'TEXT' || theReply.sfType == '3DMF') {
  452.             DoOpenFile(&theReply.sfFile);
  453.         } else if( theReply.sfType == 'PICT' && theDocument && theDocument->documentGroup) {
  454.             PicHandle            thePict;
  455.             TQ3StoragePixmap     textureImage;
  456.             
  457.             // get the picture from the file
  458.             thePict = OpenPICTFile(&theReply.sfFile);
  459.             
  460.             // make a texture
  461.             TextureFromPICT( thePict, &textureImage);
  462.             AddTextureToDocument( theDocument, &textureImage);
  463.             
  464.             // and free the space occupied by the picture
  465.             KillPicture(thePict) ;
  466.         
  467.         }
  468.     }
  469. #else
  470.  
  471.     // read for podium files
  472.     if (theReply.sfGood) {
  473.         // podium's slide files are PICT files
  474.         if( theReply.sfType == 'PICT' ) {
  475.  
  476.             short            refNum;
  477.             DocumentPtr        theDocument;
  478.             PicHandle        theBackgroundPict ;
  479.             OSErr            theErr ;
  480.             
  481.             if((theErr = FSpOpenDF(&theReply.sfFile, fsRdPerm, &refNum)) != noErr )
  482.                 return ;
  483.         
  484.             if ((theDocument = NewDocument(NULL, NULL)) != nil) {
  485.                 Rect            bounds;
  486.                 PicHandle        thePict;
  487.                 GWorldPtr        savedGWorld ;
  488.                 GDHandle        savedDevice ;
  489.                 
  490.                 GetGWorld(&savedGWorld,&savedDevice);
  491.                 
  492.                 theBackgroundPict = OpenPICTFile(&theReply.sfFile);
  493.                 bounds = (**theBackgroundPict).picFrame;
  494.  
  495.                 theErr = UpdateGWorld(&theDocument->screenBuffer, 16, &bounds, nil, nil, 0L ) ;
  496.                 if( (theErr = UpdateGWorld(&theDocument->bgOffscreen, 16, &bounds, nil, nil, 0L )) != noErr )  {
  497.                     return ;
  498.                 }
  499.                 
  500.                 // draw the picture into the offscreen    
  501.                 SetGWorld( theDocument->bgOffscreen , nil ) ;
  502.                 DrawPicture( theBackgroundPict, &bounds ) ;
  503.                 SetGWorld(savedGWorld,savedDevice);
  504.                 
  505.                 SizeWindow(theDocument->theWindow, bounds.right - bounds.left, bounds.bottom - bounds.top, false);
  506.                 {
  507.                     Rect    screenRect = (**GetMainDevice()).gdRect;
  508.                     Rect    winRect = theDocument->theWindow->portRect ;
  509.             
  510.                     CenterRectInRect(&screenRect, &winRect) ;
  511.                     MoveWindow(theDocument->theWindow,winRect.left,winRect.top,false);
  512.                 }
  513.                 SetWTitle(theDocument->theWindow, theReply.sfFile.name);
  514.                 ShowWindow(theDocument->theWindow) ;
  515.  
  516.             } else {
  517.             
  518.                 SysBeep(1);
  519.                 FSClose(refNum);
  520.                 return;
  521.                 
  522.             }
  523.         }
  524.         else if(theDocument != nil && (theReply.sfType == 'TEXT' || theReply.sfType == '3DMF')) {
  525.  
  526.             // did we try to open a metafile ???
  527.         
  528.             OSErr                result;
  529.             short                refNum;
  530.             DocumentPtr         theDocument;
  531.             FInfo                fndrInfo ;
  532.             TQ3Boolean            isText ;
  533.             
  534.             isText = (theReply.sfType == 'TEXT') ;
  535.             
  536.             if ((result = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &refNum)) != noErr)
  537.                 return ;
  538.                 
  539.             theDocument->fRefNum = refNum;
  540.             
  541.             ReadDocumentFile( theDocument, isText ) ;
  542.             AdjustCamera(theDocument,
  543.                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  544.                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);
  545.         } 
  546.     }
  547. #endif
  548.  
  549. }
  550.  
  551.  
  552. Boolean DoSaveAsDocument(DocumentPtr theDocument)
  553. {    short                theResult;
  554.     Str255                thePrompt, theName;
  555.     StandardFileReply    theReply;
  556.  
  557.     if (! theDocument)
  558.         return(false);
  559.  
  560.     GetIndString(thePrompt, FileStringsID, slSavePromptIndex);
  561.     GetWTitle(theDocument->theWindow, theName);
  562.     StandardPutFile( (ConstStr255Param) &thePrompt, (ConstStr255Param) &theName, &theReply);
  563.  
  564.     if (theReply.sfGood) {
  565.         if (!theReply.sfReplacing) {
  566.             if ((theResult = FSpCreate(&theReply.sfFile, FileCreator, FileType, theReply.sfScript)) != noErr) {
  567.                 SysBeep(1);
  568.                 return(false);
  569.             }
  570.         }
  571.         if (theDocument->fRefNum) {
  572.             theResult = FSClose(theDocument->fRefNum);
  573.         }
  574.         if ((theResult = FSpOpenDF(&theReply.sfFile, fsRdWrPerm, &theDocument->fRefNum)) != noErr) {
  575.             SysBeep(1);
  576.             return(false);
  577.         }
  578.  
  579.         if ((theResult = WriteDocumentFile(theDocument)) != noErr) {
  580.             SysBeep(1);
  581.             return(false);
  582.         }
  583.  
  584.         SetWTitle(theDocument->theWindow, theReply.sfFile.name);
  585.         theDocument->dirty = false;
  586.  
  587.     } else {
  588.         return(false);
  589.     }
  590.     return(true);
  591. }
  592.  
  593.  
  594. Boolean DidSaveDocument(DocumentPtr theDocument)
  595. {
  596.  
  597.     if ( theDocument == nil )
  598.         return(false);
  599.  
  600.     if (theDocument->fRefNum) {
  601.         if (WriteDocumentFile(theDocument)) {
  602.             SysBeep(1);
  603.             return(false);
  604.         } else {
  605.             theDocument->dirty = false;
  606.         }
  607.         return(true);
  608.     } else {
  609.         return(DoSaveAsDocument(theDocument));
  610.     }
  611. }
  612.  
  613.  
  614. void DoRevertDocument(DocumentPtr theDocument)
  615.  
  616. {    Str255        theName;
  617.  
  618.     if (! theDocument)
  619.         return;
  620.  
  621.     if (theDocument->fRefNum) {
  622.         GetWTitle(theDocument->theWindow, theName);
  623.         ParamText( (ConstStr255Param) &theName, (ConstStr255Param) "", (ConstStr255Param) "", (ConstStr255Param) "");
  624.         if (Alert(idRevertALRT, 0L) == 1) {
  625.             FInfo                fndrInfo ;
  626.         
  627.             // we assume the FSSpec in the document is valid, get the file information
  628.             // we need to know the file type
  629.             
  630.             FSpGetFInfo( &theDocument->theFileSpec, &fndrInfo ) ;
  631.             
  632.             // pull out the file type
  633.             
  634.             ReadDocumentFile(theDocument, (fndrInfo.fdType == 'TEXT')) ;
  635.         }
  636.     }
  637. }
  638.  
  639.  
  640.